package main

import "fmt"

func main() {
	tower := newManageTower()
	boeing := &boeingPlane{
		tower,
	}
	airbus := &airBusPlane{
		tower,
	}
	boeing.landing()
	airbus.landing()
	boeing.takeOff()
}

/*
中介者模式是一种行为设计模式， 能让程序减少对象之间混乱无序的依赖关系。
该模式会限制对象之间的直接交互， 迫使它们通过一个中介者对象进行交互。
*/

type mediator interface {
	canLanding(airplane airplane) bool
	notifyAboutDeparture()
}

type manageTower struct {
	isRunwayFree bool
	airportQueue []airplane
}

func (tower *manageTower) canLanding(airplane airplane) bool {
	if tower.isRunwayFree {
		tower.isRunwayFree = false
		return true
	}

	tower.airportQueue = append(tower.airportQueue, airplane)
	return false
}

func (tower *manageTower) notifyAboutDeparture() {
	if !tower.isRunwayFree {
		tower.isRunwayFree = true
	}

	if len(tower.airportQueue) > 0 {
		firstPlaneWaitingQueue := tower.airportQueue[0]
		tower.airportQueue = tower.airportQueue[1:]
		firstPlaneWaitingQueue.permitLanding()
	}
}

func newManageTower() *manageTower {
	return &manageTower{
		isRunwayFree: true,
	}
}

type airplane interface {
	landing()
	takeOff()
	permitLanding()
}

type airBusPlane struct {
	mediator
}

func (a *airBusPlane) landing() {
	if !a.mediator.canLanding(a) {
		fmt.Println("Airplane AirBus: 飞机跑到正在被占用，无法降落！")
		return
	}
	fmt.Println("Airplane AirBus: 已成功降落！")
}

func (a *airBusPlane) takeOff() {
	fmt.Println("Airplane AirBus: 正在起飞离开跑道！")
	a.mediator.notifyAboutDeparture()
}

func (a *airBusPlane) permitLanding() {
	fmt.Println("Airplane AirBus: 收到指挥塔信号，允许降落，正在降落！")
	a.landing()
}

type boeingPlane struct {
	mediator
}

func (b *boeingPlane) landing() {
	if !b.mediator.canLanding(b) {
		fmt.Println("Airplane Boeing: 飞机跑道正在被占用，无法降落")
		return
	}
	fmt.Println("Airplane Boeing: 已成功降落")
}

func (b *boeingPlane) takeOff() {
	fmt.Println("Airplane Boeing: 正在起飞离开跑道")
	b.mediator.notifyAboutDeparture()
}

func (b *boeingPlane) permitLanding() {
	fmt.Println("Airplane Boeing: 收到指挥塔信号，允许降落，正在降落")
	b.landing()
}

/*
定义一组会相互调用，拥有强耦合的组件。
指定中介者接口以及中介者与各个组件之间的通信方式。在大多数情况下中介者接口中必须有一个Notify/Notification方法从组件接收通知。
创建具体中介者实现，该实现将会存储其管理的所有Component对象的引用
组件对象应该保存中介者的引用，如果想在不同上下文下使用不同的中介者实现，那么应该通过中介者接口类型保存对具体中介者的引用。
将组件对象调用其他组件对象的方法提炼到中介者中，组件对象调用中介者的通知方法，由中介者再去调用相对应的组件的方法，从而完成组件与组件间的解耦。
*/

/*
中介者模式（Mediator Pattern）又叫作调解者模式或调停者模式。 用一个中介对象封装一系列对象交互， 中介者使各对象不需要显式地相互作用， 从而使其耦合松散， 而且可以独立地改变它们之间的交互， 属于行为型设计模式。

中介者模式主要适用于以下应用场景。

系统中对象之间存在复杂的引用关系，产生的相互依赖关系结构混乱且难以理解。
交互的公共行为，如果需要改变行为，则可以增加新的中介者类。
中介者模式的优点

减少类间依赖，将多对多依赖转化成一对多，降低了类间耦合。
类间各司其职，符合迪米特法则。
中介者模式的缺点

中介者模式将原本多个对象直接的相互依赖变成了中介者和多个组件类的依赖关系。
当组件类越多时，中介者就会越臃肿，变得复杂且难以维护。
*/
